﻿#ifndef JTHREAD_H
#define JTHREAD_H

#include "jthreadpool_global.h"
#include <limits.h>

// interface JThreadObserver

/**
 * @brief The JThreadObserver class
 */
class JThreadObserver
{
public:

    /**
     * @brief started
     */
    virtual void started() {}

    /**
     * @brief finished
     */
    virtual void finished() {}

    /**
     * @brief terminated
     */
    virtual void terminated() {}

    /**
     * @brief suspended
     */
    virtual void suspended() {} //!!!

    /**
     * @brief resumed
     */
    virtual void resumed() {}   //!!!
};

// - class JThread -

class JThreadPrivate;
class QThread;

/**
 * @brief The JThread class
 */
class JTHREADPOOL_EXPORT JThread
{
public:
    /**
     * @brief currentThreadId
     * @return
     */
    static JConcurrent::HANDLE currentThreadId();

    /**
     * @brief currentThread
     * @return
     */
    static JThread currentThread();

    /**
     * @brief idealThreadCount
     * @return
     */
    static int idealThreadCount();

    /**
     * @brief yieldCurrentThread
     */
    static void yieldCurrentThread();

    /**
     * @brief JThread
     */
    explicit JThread();

    /**
     * @brief JThread
     * @param other
     */
    explicit JThread(QThread *other);
    ~JThread();

    /**
     * @brief The Priority enum
     */
    enum Priority {
        IdlePriority,

        LowestPriority,
        LowPriority,
        NormalPriority,
        HighPriority,
        HighestPriority,

        TimeCriticalPriority,

        InheritPriority
    };

    /**
     * @brief setPriority
     * @param priority
     */
    void setPriority(Priority priority);

    /**
     * @brief priority
     * @return
     */
    Priority priority() const;

    /**
     * @brief isFinished
     * @return
     */
    bool isFinished() const;

    /**
     * @brief isRunning
     * @return
     */
    bool isRunning() const;

    /**
     * @brief setStackSize
     * @param stackSize
     */
    void setStackSize(unsigned int stackSize);

    /**
     * @brief stackSize
     * @return
     */
    unsigned int stackSize() const;

    /**
     * @brief exit
     * @param retcode
     */
    void exit(int retcode = 0);

    /**
     * @brief start
     * @param priority
     */
    void start(Priority priority = InheritPriority);

    /**
     * @brief terminate
     */
    void terminate();

    /**
     * @brief quit
     */
    void quit();

    /**
     * @brief suspend
     */
    void suspend(); //!!!

    /**
     * @brief resume
     */
    void resume();  //!!!

public:
    // default argument causes thread to block indefinetely

    /**
     * @brief wait
     * @param time
     * @return
     */
    bool wait(unsigned long time = ULONG_MAX);

    /**
     * @brief sleep
     * @param secs
     */
    static void sleep(unsigned long secs);

    /**
     * @brief msleep
     * @param msecs
     */
    static void msleep(unsigned long msecs);

    /**
     * @brief usleep
     * @param usecs
     */
    static void usleep(unsigned long usecs);

protected:
    /**
     * @brief run
     */
    virtual void run();

    /**
     * @brief exec
     * @return
     */
    int exec();

    /**
     * @brief setTerminationEnabled
     * @param enabled
     */
    static void setTerminationEnabled(bool enabled = true);

    /**
     * @brief data
     * @return
     */
    QThread *data() const;

private:
    J_DISABLE_COPY(JThread)
    J_DECLARE_PRIVATE(JThread)
    J_DECLARE_OBSERVER(JThread)
    friend class JThreadDelegate;
};

#endif // JTHREAD_H
